package fr.umlv.search;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.ListModel;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.TableModelEvent;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.AbstractTableModel;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.FileableCmisObject;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.ItemIterable;
import org.apache.chemistry.opencmis.client.api.Property;
import org.apache.chemistry.opencmis.client.api.QueryResult;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;

import fr.umlv.authentication.SessionHandler;
import fr.umlv.metadata.CategoryUtils;

// TODO: Auto-generated Javadoc
/**
 * The Class SearchModel.
 */
public class SearchModel extends AbstractTableModel implements
ListModel, Serializable{
	
	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;

	/** The Constant ALL_INDEX. */
	public static final int ALL_INDEX = TableModelEvent.HEADER_ROW;

	/** The Constant NAME. */
	public static final int NAME = 0;

	/** The Constant SIZE. */
	public static final int SIZE = 1;

	/** The Constant TYPE. */
	public static final int TYPE = 2;

	/** The Constant MODIFIED. */
	public static final int MODIFIED = 3;
	
	/** The Constant LOCATION. */
	public static final int GOTO_LOCATION = 5;
	
	/** The Constant PARTIAL PATH */
	public static final int LOCATION = 4;

	/** The Constant BROWSE. */
	public static final int BROWSE = 0;

	/** The Constant EDIT. */
	public static final int EDIT = 1;

	/** The Constant DELETE. */
	public static final int DELETE = 2;

	/** The column names. */
	protected String[] columnNames = { "Name", "Size", "Type", "Modified", "Go", "Location" };

	/** The search results. */
	protected List<CmisObject> searchResults;

	/** The list data listeners. */
	protected EventListenerList listDataListeners;

	/** The fsv. */
	protected FileSystemView fsv;

	/** The use file hiding. */
	protected boolean useFileHiding;

	/** The sort by. */
	protected int sortBy;

	/** The state. */
	protected int state;

	/** The directory. */
	protected CmisObject directory;

	//private ClientModel model;
	
	/** The bundle. */
	private ResourceBundle bundle = ResourceBundle.getBundle("kiyut.ekspos.BrowserWindow",SessionHandler.getLocale());
	
	/**
	 * Instantiates a new search model.
	 *
	 * @param search_rapid the search_rapid
	 * @throws CmisNoResultsException the cmis no results exception
	 * @throws MalformedCritersException the malformed criters exception
	 */
	public SearchModel(String search_rapid) throws CmisNoResultsException, MalformedCritersException{
		
		checkPunctuations(search_rapid);
		
		searchResults = Collections.synchronizedList(new ArrayList<CmisObject>());
		String requestFileName = "CONTAINS(d,'cmis:name:*" + search_rapid + "*')";
		String requete = "select d.cmis:objectId from cmis:document d where " + requestFileName;
		
		buildResultsFromQuery(requete);
		
		requete = "select d.cmis:objectId from cmis:folder d where " + requestFileName;
		
		buildResultsFromQuery(requete);	
		
		listDataListeners = new EventListenerList();

		
		columnNames = new String[6];
		columnNames[0] = bundle.getString("DetailView.NameColumn");
		columnNames[1] = bundle.getString("DetailView.SizeColumn");
		columnNames[2] = bundle.getString("DetailView.TypeColumn");  
		columnNames[3] = bundle.getString("DetailView.LastModificationColumn");
		columnNames[5] = "";
		columnNames[4] = bundle.getString("DetailView.Location");
		
		
		if(searchResults.size()==0){
			throw new CmisNoResultsException();
		}
		
		
	}
	
	
	

	/**
	 * Builds the results from query.
	 *
	 * @param requete the requete
	 */
	private void buildResultsFromQuery(String requete) {
		Session session = SessionHandler.getClientSession().getSession();
		
		ItemIterable<QueryResult> resultats = session.query(requete, false);
        for(QueryResult r : resultats){
        	for (PropertyData<?> prop : r.getProperties()) {
                for(Object t : prop.getValues()){
                	String t_to_string = (String) t;
                	CmisObject cmisObject = session.getObject(new ObjectIdImpl(t_to_string));
                	searchResults.add(cmisObject);
                }
        	}
        }
	}




	/**
	 * Instantiates a new search model.
	 *
	 * @param useFileHiding the use file hiding
	 * @param sortBy the sort by
	 * @param propertiesSearch the properties search
	 * @throws CmisNoResultsException the cmis no results exception
	 * @throws NoCritersException the no criters exception
	 * @throws MalformedCritersException the malformed criters exception
	 */
	public SearchModel(boolean useFileHiding, int sortBy, Map<String, String> propertiesSearch ) throws CmisNoResultsException, NoCritersException, MalformedCritersException{

		
		searchResults = Collections.synchronizedList(new ArrayList<CmisObject>());
		List<String> categoriesSelectedName = new ArrayList<String>();
		List<String> categoriesSelectedId = new ArrayList<String>();
		
		Session session = SessionHandler.getClientSession().getSession();
		
		checkPunctuations(propertiesSearch.get("filename"));
		checkPunctuations(propertiesSearch.get("title"));
		checkPunctuations(propertiesSearch.get("description"));
		checkPunctuations(propertiesSearch.get("author"));
		
		String fileName = "*" + propertiesSearch.get("filename") + "*";
		String fileTitle = "*" + propertiesSearch.get("title") + "*";
		String fileDescription = "*" + propertiesSearch.get("description") + "*";
		String fileAuthor = "*" + propertiesSearch.get("author") + "*";
		String fileModificationFrom = propertiesSearch.get("modification_from");
		String fileModificationTo = propertiesSearch.get("modification_to");
		String fileCreationFrom = propertiesSearch.get("creation_from");
		String fileCreationTo = propertiesSearch.get("creation_to");
		String treeSpecificSpace = propertiesSearch.get("tree_specific_space");
		treeSpecificSpace = treeSpecificSpace.replace("/Espace racine", "");
		String listCategories = propertiesSearch.get("list_categories");
		if(!listCategories.equals("")){
			for(String categPath : listCategories.split(", ")){
				categoriesSelectedName.add(categPath);
			}	
			categoriesSelectedId = CategoryUtils.getCategoriesIdFromCategoriesName(categoriesSelectedName);
		}
		String isSelectedSpecificSpace = propertiesSearch.get("button_specific_space");
		
		
		String requestFileName = "CONTAINS(d,'cmis:name:" + fileName + "')";
		String requestFileTitle = "CONTAINS(t,'cm:title:" + fileTitle + "')";
		String requestFileDescription = "CONTAINS(t,'cm:description:" + fileDescription + "')";
		String requestFileAuthor = "CONTAINS(a,'cm:author:" + fileAuthor + "')";
		
		
		String requestModification = "";
		
		if(fileModificationFrom.matches("\\d\\d/\\d\\d/\\d\\d\\d\\d")){
			if(fileModificationTo.matches("\\d\\d/\\d\\d/\\d\\d\\d\\d")){
				requestModification = "and d.cmis:lastModificationDate > " + formatDateForRequest(fileModificationFrom,true) + " and d.cmis:lastModificationDate < " + formatDateForRequest(fileModificationTo,false);
			}else{
				requestModification = "and d.cmis:lastModificationDate > " + formatDateForRequest(fileModificationFrom,true);
			}
		}else if(fileModificationTo.matches("\\d\\d/\\d\\d/\\d\\d\\d\\d")){
			requestModification = "and d.cmis:lastModificationDate < " + formatDateForRequest(fileModificationTo,false);
		}
		
		
		
		String requestCreation = "";
		
		if(fileCreationFrom.matches("\\d\\d/\\d\\d/\\d\\d\\d\\d")){
			if(fileCreationTo.matches("\\d\\d/\\d\\d/\\d\\d\\d\\d")){
				requestCreation = "and d.cmis:creationDate > " + formatDateForRequest(fileCreationFrom,true) + " and d.cmis:creationDate < " + formatDateForRequest(fileCreationTo,false);
			}else{
				requestCreation = "and d.cmis:creationDate > " + formatDateForRequest(fileCreationFrom,true);
			}
		}else if(fileCreationTo.matches("\\d\\d/\\d\\d/\\d\\d\\d\\d")){
			requestCreation = "and d.cmis:creationDate < " + formatDateForRequest(fileCreationTo,false);
		}
		
		if(categoriesSelectedName.isEmpty() && fileName.equals("**") && fileTitle.equals("**") && fileDescription.equals("**") && fileAuthor.equals("**") && fileModificationFrom.equals("  /  /    ") && fileModificationTo.equals("  /  /    ") && fileCreationFrom.equals("  /  /    ") && fileCreationTo.equals("  /  /    ") && treeSpecificSpace.equals("") && !isSelectedSpecificSpace.equals("true")){
			throw new NoCritersException();
		}
		
	
		
		if(!categoriesSelectedName.isEmpty() && fileName.equals("**") && fileTitle.equals("**") && fileDescription.equals("**") && fileAuthor.equals("**") && fileModificationFrom.equals("  /  /    ") && fileModificationTo.equals("  /  /    ") && fileCreationFrom.equals("  /  /    ") && fileCreationTo.equals("  /  /    ") && treeSpecificSpace.equals("") && !isSelectedSpecificSpace.equals("true")){
			List<String> objectsId = CategoryUtils.getObjectIdsFromCategoriesName(categoriesSelectedName);
			for(String id : objectsId){
				CmisObject cmisObject = session.getObject(new ObjectIdImpl(id));
				searchResults.add(cmisObject);
			}
		}
		else if(isSelectedSpecificSpace.equals("true") && !treeSpecificSpace.equals("") && categoriesSelectedName.isEmpty() && fileName.equals("**") && fileTitle.equals("**") && fileDescription.equals("**") && fileAuthor.equals("**") && fileModificationFrom.equals("  /  /    ") && fileModificationTo.equals("  /  /    ") && fileCreationFrom.equals("  /  /    ") && fileCreationTo.equals("  /  /    ")){
			Folder f = (Folder) session.getObjectByPath(treeSpecificSpace);
			ItemIterable<CmisObject> iterable  = f.getChildren();
			Iterator<CmisObject> iterator = iterable.iterator();
			while(iterator.hasNext()){
				CmisObject cmisobj = iterator.next();
				searchResults.add(cmisobj);
			}
		}
		else{
			if(propertiesSearch.get("button_space_only").equals("false")){
				//String requete = "select cmis:name from cmis:document where cmis:name like '" + fileName + "' and cmis:t";
				String requete;
				if(fileTitle.equals("**") && fileDescription.equals("**") && fileAuthor.equals("**")){
					requete = "select d.cmis:objectId from cmis:document d where " + requestFileName + " " + requestCreation + " " + requestModification;
				}else{
					requete = "select d.cmis:objectId from cmis:document d join cm:titled t on d.cmis:objectid = t.cmis:objectid join cm:author a on d.cmis:objectid = a.cmis:objectid where " + requestFileName + " and " + requestFileAuthor + " and " + requestFileTitle + " and " + requestFileDescription + " " + requestCreation + " " + requestModification;
				}
				ItemIterable<QueryResult> resultats = session.query(requete, false);
		        for(QueryResult r : resultats){
		        	for (PropertyData<?> prop : r.getProperties()) {
		                for(Object t : prop.getValues()){
		                	String t_to_string = (String) t;
		                	CmisObject cmisObject = session.getObject(new ObjectIdImpl(t_to_string));
		                	FileableCmisObject fileableCmisObject = (FileableCmisObject) cmisObject;
		                	boolean isAdded = false;
		                	
		                	
		                	if (!categoriesSelectedId.isEmpty()){
	            				List<String> objectCategoriesId = CategoryUtils.getCategoriesIdFromObject(cmisObject);
	            				for(String categSelectedId : categoriesSelectedId){
	            					if(objectCategoriesId.contains(categSelectedId)){
	            						//si categ ok, on verifie si folder ok
	            						if(isSelectedSpecificSpace.equals("true") && !treeSpecificSpace.equals("")){
	    			            			
	    			            			Folder f_to_search = (Folder) session.getObjectByPath(treeSpecificSpace);
	    			            			String id_folder_to_search = f_to_search.getId();
	    			            			
	    			            			for(Folder f : fileableCmisObject.getParents()){ //parents de l'objet trouve
	    				                		if(f.getId().equals(id_folder_to_search)){
	    				                			if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}	
	    				                		}
	    				                	}
	    	            				}else{
	    	            					//categ ok, on ajoute car pas de contraintes au niveau de folder
	    	            					if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}
	    	            				}
	            					}
	            				}
		                	}
	            			else{
	            				if(isSelectedSpecificSpace.equals("true") && !treeSpecificSpace.equals("")){
			            			
			            			Folder f_to_search = (Folder) session.getObjectByPath(treeSpecificSpace);
			            			String id_folder_to_search = f_to_search.getId();
			            			
			            			for(Folder f : fileableCmisObject.getParents()){ //parents de l'objet trouve
				                		if(f.getId().equals(id_folder_to_search)){
				                			if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}	
				                		}
				                	}
	            				}else{
	            					//categ ok, on ajoute car pas de contraintes au niveau de folder
	            					if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}
	            				}
	            			}    	           	
		                }          
		            }
		        }
			}
			
			
			if(propertiesSearch.get("button_space_only").equals("true") || propertiesSearch.get("button_all_elements").equals("true")){
				String requete;
				if(fileTitle.equals("**") && fileDescription.equals("**")){
					requete = "select d.cmis:objectId from cmis:folder d where " + requestFileName + " " + requestCreation + " " + requestModification;
				}else{
					requete = "select d.cmis:objectId from cmis:folder d join cm:titled t on d.cmis:objectid = t.cmis:objectid where " + requestFileName + " and " + requestFileTitle + " and " + requestFileDescription + " " + requestCreation + " " + requestModification;
				}
				ItemIterable<QueryResult> resultats = session.query(requete, false);
		        for(QueryResult r : resultats){
		        	for (PropertyData<?> prop : r.getProperties()) {
		                for(Object t : prop.getValues()){
		                	String t_to_string = (String) t;
		                	CmisObject cmisObject = session.getObject(new ObjectIdImpl(t_to_string));
		                	FileableCmisObject fileableCmisObject = (FileableCmisObject) cmisObject;
		                	boolean isAdded = false;
		                	
		                	if (!categoriesSelectedId.isEmpty()){
	            				List<String> objectCategoriesId = CategoryUtils.getCategoriesIdFromObject(cmisObject);
	            				for(String categSelectedId : categoriesSelectedId){
	            					if(objectCategoriesId.contains(categSelectedId)){
	            						
	            						//si categ ok, on verifie si folder ok
	            						if(isSelectedSpecificSpace.equals("true") && !treeSpecificSpace.equals("")){
	    			            			
	    			            			Folder f_to_search = (Folder) session.getObjectByPath(treeSpecificSpace);
	    			            			String id_folder_to_search = f_to_search.getId();
	    			            			
	    			            			for(Folder f : fileableCmisObject.getParents()){ //parents de l'objet trouve
	    				                		if(f.getId().equals(id_folder_to_search)){
	    				                			if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}		
	    				                		}
	    				                	}
	    	            				}else{
	    	            					//categ ok, on ajoute car pas de contraintes au niveau de folder
	    	            					if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}	
	    	            				}
	            					}
	            				}
		                	}
	            			else{
	            				if(isSelectedSpecificSpace.equals("true") && !treeSpecificSpace.equals("")){
			            			
			            			Folder f_to_search = (Folder) session.getObjectByPath(treeSpecificSpace);
			            			String id_folder_to_search = f_to_search.getId();
			            			
			            			for(Folder f : fileableCmisObject.getParents()){ //parents de l'objet trouve
				                		if(f.getId().equals(id_folder_to_search)){
				                			if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}	
				                		}
				                	}
	            				}else{
	            					//categ ok, on ajoute car pas de contraintes au niveau de folder
	            					if(!isAdded){ searchResults.add(cmisObject); isAdded=true;}	
	            				}
	            			}    	           	
		                }          
		            }
		        }
			}
			
			
		}
		
		
		this.useFileHiding = useFileHiding;
		this.sortBy = sortBy;
		listDataListeners = new EventListenerList();

		
		columnNames = new String[6];
		columnNames[0] = bundle.getString("DetailView.NameColumn");
		columnNames[1] = bundle.getString("DetailView.SizeColumn");
		columnNames[2] = bundle.getString("DetailView.TypeColumn");  
		columnNames[3] = bundle.getString("DetailView.LastModificationColumn");
		columnNames[5] = "";
		columnNames[4] = bundle.getString("DetailView.Location");
		
		if(searchResults.size()==0){
			throw new CmisNoResultsException();
		}
	}

	/**
	 * Format date for request.
	 *
	 * @param initialDate the initial date
	 * @param midnight the midnight
	 * @return the string
	 */
	private String formatDateForRequest(String initialDate,boolean midnight){	
		String[] elems =  initialDate.split("/");	
		return "TIMESTAMP '" + elems[2] + "-" + elems[1] + "-" + elems[0] + "T" + (midnight?"00:00:00.000+00:00":"23:59:59.999+00:00") + "'";
	}

	/* (non-Javadoc)
	 * @see javax.swing.ListModel#getSize()
	 */
	public int getSize() {
		return getRowCount();
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getColumnCount()
	 */
	public int getColumnCount() {
		return columnNames.length;
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.AbstractTableModel#getColumnName(int)
	 */
	@Override
	public String getColumnName(int col) {
		return columnNames[col];
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getRowCount()
	 */
	public int getRowCount() {
		return searchResults.size();
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getValueAt(int, int)
	 */
	public Object getValueAt(int row, int col) {
		Object object = null;
		CmisObject file = searchResults.get(row);

		
		switch (col) {
		case NAME:
			object = file;
			break;
		case SIZE:
			object = null;
			if (BaseTypeId.CMIS_DOCUMENT.equals(file.getBaseTypeId())) {
				return ((Document) file).getContentStreamLength();
			}
			break;
		case TYPE:
			String str = file.getType().getDisplayName();
			if (str == null) {
				str = "";
			}
			object = str;
			break;
		case MODIFIED:
			Date date = new Date();
			date.setTime(file.getLastModificationDate().getTimeInMillis());
			object = date;
			break;
			
		case LOCATION:	
		case GOTO_LOCATION:
			FileableCmisObject fileAble = (FileableCmisObject) file;
			String completePath = fileAble.getPaths().get(0);
			String parentPath = completePath.substring(0, completePath.lastIndexOf("/"));
			object = parentPath + "/";
			break;

		}
		return object;
	}
		

	/* (non-Javadoc)
	 * @see javax.swing.ListModel#getElementAt(int)
	 */
	public Object getElementAt(int index) {
		return getValueAt(index, 0);
	}

	/**
	 * Gets the file.
	 *
	 * @param index the index
	 * @return the file
	 */
	public CmisObject getFile(int index) {
		return (CmisObject) getValueAt(index, 0);
	}

	/**
	 * Refresh.
	 */
	public synchronized void refresh() {
		

		// Group the folder & file
		List<Folder> dirs = new ArrayList<Folder>();
		List<Document> files = new ArrayList<Document>();

		List<CmisObject> iterable = new ArrayList<CmisObject>();
		
		for(CmisObject obj : searchResults){
			iterable.add(obj);
		}
		
		
		searchResults.clear();
		
		Iterator<CmisObject> iterator = iterable.iterator();
		

		while (iterator.hasNext()) {
			CmisObject cmisobj = iterator.next();

			if (BaseTypeId.CMIS_DOCUMENT.equals(cmisobj.getBaseTypeId())) {
				files.add(((Document) cmisobj));
			} else if (BaseTypeId.CMIS_FOLDER.equals(cmisobj
					.getBaseTypeId())) {
				dirs.add(((Folder) cmisobj));
			}
		}

		switch (sortBy) {
		case NAME:
			Collections.sort(dirs,new CmisObjectNameComparator());
			Collections.sort(files,new CmisObjectNameComparator());
			break;
		case SIZE:
			Collections.sort(dirs,new CmisObjectSizeComparator());
			Collections.sort(files,new CmisObjectSizeComparator());
			break;
		case TYPE:
			Collections.sort(dirs,new CmisObjecTypeComparator());
			Collections.sort(files,new CmisObjecTypeComparator());
			break;
		case MODIFIED:
			Collections.sort(dirs,new CmisObjectModifiedComparator());
			Collections.sort(files,new CmisObjectModifiedComparator());
			break;
		}
		
		searchResults.addAll(dirs);
		searchResults.addAll(files);

		fireTableDataChanged();
		fireContentsChanged(ALL_INDEX, ALL_INDEX);
	}

	/**
	 * Rename file.
	 *
	 * @param index the index
	 * @param filename the filename
	 * @return true, if successful
	 * @throws SecurityException the security exception
	 */
	public synchronized boolean renameFile(int index, String filename)
	throws SecurityException {

		CmisObject file = getFile(index);

		Map<String,String> modifyFolderProps = new HashMap<String, String>();

		for(Property<?> p :file.getProperties()){
			modifyFolderProps.put(p.getId(),p.getValueAsString());
		}

		modifyFolderProps.put(PropertyIds.NAME,filename);
		file.updateProperties(modifyFolderProps,true);

		fireTableRowsUpdated(index,index); 
		fireContentsChanged(index,index);

		return true;
	}

	/**
	 * Removes the.
	 *
	 * @param index the index
	 * @return the object
	 */
	public Object remove(int index) {
		Object object = searchResults.remove(index);
		fireTableRowsDeleted(index, index);
		fireIntervalRemoved(index, index);
		return object;
	}

	/**
	 * Index of.
	 *
	 * @param elem the elem
	 * @return the int
	 */
	public int indexOf(Object elem) {
		return searchResults.indexOf(elem);
	}

	/**
	 * Checks if is traversable.
	 *
	 * @param index the index
	 * @return true, if is traversable
	 */
	public boolean isTraversable(int index) {
		CmisObject obj = getFile(index);

		if (BaseTypeId.CMIS_FOLDER.equals(obj.getBaseTypeId())) {
			return true;
		}

		return false;
	}

	/**
	 * Checks if is file hiding enabled.
	 *
	 * @return true, if is file hiding enabled
	 */
	public boolean isFileHidingEnabled() {
		return this.useFileHiding;
	}

	/**
	 * Sets the file hiding enabled.
	 *
	 * @param useFileHiding the new file hiding enabled
	 */
	public void setFileHidingEnabled(boolean useFileHiding) {
		this.useFileHiding = useFileHiding;
	}

	/**
	 * Gets the sort by.
	 *
	 * @return the sort by
	 */
	public int getSortBy() {
		return this.sortBy;
	}

	/**
	 * Sets the sort by.
	 *
	 * @param sortBy the new sort by
	 */
	public void setSortBy(int sortBy) {
		this.sortBy = sortBy;
	}

	/**
	 * Gets the current directory.
	 *
	 * @return the current directory
	 */
	public CmisObject getCurrentDirectory() {
		return this.directory;
	}

	/**
	 * Sets the current directory.
	 *
	 * @param directory the new current directory
	 */
	public void setCurrentDirectory(CmisObject directory) {
		if (directory == null) {
			// this.directory = fsv.getHomeDirectory();
		} else {
			this.directory = directory;
		}
	}

	/**
	 * Gets the file system view.
	 *
	 * @return the file system view
	 */
	public FileSystemView getFileSystemView() {
		return fsv;
	}

	/**
	 * Sets the file system view.
	 *
	 * @param fsv the new file system view
	 */
	public void setFileSystemView(FileSystemView fsv) {
		this.fsv = fsv;
	}

	/**
	 * Gets the state.
	 *
	 * @return the state
	 */
	public int getState() {
		return this.state;
	}

	/**
	 * Sets the state.
	 *
	 * @param state the new state
	 */
	public void setState(int state) {
		this.state = state;
	}

	/* (non-Javadoc)
	 * @see javax.swing.ListModel#addListDataListener(javax.swing.event.ListDataListener)
	 */
	public void addListDataListener(ListDataListener l) {
		listDataListeners.add(ListDataListener.class, l);
	}

	/* (non-Javadoc)
	 * @see javax.swing.ListModel#removeListDataListener(javax.swing.event.ListDataListener)
	 */
	public void removeListDataListener(ListDataListener l) {
		listDataListeners.remove(ListDataListener.class, l);
	}

	/**
	 * Fire contents changed.
	 *
	 * @param index0 the index0
	 * @param index1 the index1
	 */
	public void fireContentsChanged(int index0, int index1) {
		Object[] listeners = listDataListeners.getListenerList();
		ListDataEvent e = null;

		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == ListDataListener.class) {
				if (e == null) {
					e = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED,
							index0, index1);
				}
				((ListDataListener) listeners[i + 1]).contentsChanged(e);
			}
		}
	}

	/**
	 * Fire interval added.
	 *
	 * @param index0 the index0
	 * @param index1 the index1
	 */
	public void fireIntervalAdded(int index0, int index1) {
		Object[] listeners = listDataListeners.getListenerList();
		ListDataEvent e = null;

		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == ListDataListener.class) {
				if (e == null) {
					e = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED,
							index0, index1);
				}
				((ListDataListener) listeners[i + 1]).intervalAdded(e);
			}
		}
	}

	/**
	 * Fire interval removed.
	 *
	 * @param index0 the index0
	 * @param index1 the index1
	 */
	public void fireIntervalRemoved(int index0, int index1) {
		Object[] listeners = listDataListeners.getListenerList();
		ListDataEvent e = null;

		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == ListDataListener.class) {
				if (e == null) {
					e = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED,
							index0, index1);
				}
				((ListDataListener) listeners[i + 1]).intervalRemoved(e);
			}
		}
	}

	/**
	 * The Class CmisObjectNameComparator.
	 */
	public class CmisObjectNameComparator implements Comparator<CmisObject> {
		
		/* (non-Javadoc)
		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
		 */
		public int compare(CmisObject file1, CmisObject file2) {
			return file1.getName().toLowerCase().compareTo(file2.getName().toLowerCase());
		}
	}
	
	/**
	 * The Class CmisObjectSizeComparator.
	 */
	public class CmisObjectSizeComparator implements Comparator<CmisObject> {
		
		/* (non-Javadoc)
		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
		 */
		public int compare(CmisObject file1, CmisObject file2) {
			int comp;

			if (getSize(file1) < getSize(file2)) {
				comp = -1;
			} else if (getSize(file1) == getSize(file2)) {
				comp = file1.getName().toLowerCase().compareTo(file2.getName().toLowerCase());
			} else {
				comp = 1;
			}

			return comp;
		}
	}

	/**
	 * The Class CmisObjecTypeComparator.
	 */
	public class CmisObjecTypeComparator implements Comparator<CmisObject> {
		
		/* (non-Javadoc)
		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
		 */
		public int compare(CmisObject file1, CmisObject file2) {
			int comp;

			String desc1 = file1.getType().getDisplayName();
			String desc2 = file2.getType().getDisplayName();

			if (desc1 == null) {
				desc1 = "";
			}
			if (desc2 == null) {
				desc2 = "";
			}

			comp = desc1.compareTo(desc2);
			if (comp == 0) {
				comp = file1.getName().toLowerCase().compareTo(file2.getName().toLowerCase());
			}

			return comp;
		}

	}

	/**
	 * The Class CmisObjectModifiedComparator.
	 */
	public class CmisObjectModifiedComparator implements Comparator<CmisObject> {
		
		/* (non-Javadoc)
		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
		 */
		public int compare(CmisObject file1, CmisObject file2) {
			int comp;

			if (file1.getLastModificationDate().getTimeInMillis() < file2.getLastModificationDate().getTimeInMillis()) {
				comp = -1;
			} else if (file1.getLastModificationDate().getTimeInMillis() == file2.getLastModificationDate().getTimeInMillis()) {
				comp = file1.getName().toLowerCase().compareTo(file2.getName().toLowerCase());
			} else {
				comp = 1;
			}

			return comp;
		}
	}
	
	/**
	 * Gets the size.
	 *
	 * @param file the file
	 * @return the size
	 */
	public long getSize(CmisObject file){
		if (BaseTypeId.CMIS_DOCUMENT.equals(file.getBaseTypeId())) {
			return ((Document) file).getContentStreamLength();
		}
		return 0;
	}
	
	/**
	 * Check punctuations.
	 *
	 * @param field the field
	 * @throws MalformedCritersException the malformed criters exception
	 */
	private void checkPunctuations(String field) throws MalformedCritersException{
		Pattern pattern = Pattern.compile("\\p{Punct}");
		Matcher matcher = pattern.matcher(field);
		if(matcher.find()){
			throw new MalformedCritersException();
		}
	}
	
	

}
